承接昨天的話題,如果只要截取到賓士遙控器的傳輸碼,然後進行重放攻擊,就可以試駕門口的那輛賓士,那我猜你肯定現在已經在下訂 Flipper Zero 的路上,但答案是不行的。
因為賓士的遙控器使用了滾動碼(Rolling Code)的編碼方式,所以即使我們截取到控制碼,也無法進行重放攻擊。就算你運氣好,在賓士車主按下遙控器時,Flipper Zero 錄製到了訊號,賓士並沒有接收到訊號,也就是說對於賓士來說「這組 code 尚未被使用」,雖然按邏輯來說,這樣重放訊號應該要是有效的,但賓士製造商也不是如此天真,他們會在接收端加入一些防禦機制,像是「如果在一段時間內收到重複的碼,就拒絕」,所以即使你截取到控制碼,也無法進行重放攻擊,除此之外還有好幾種多重的防禦機制。
總之,別肖想外面那台賓士了,不如踏實地好好賺錢,自己買一台賓士還比較實際!
開始今天的主題前,一樣要先進行⋯⋯
引用自 Kazma 的 Flipper Zero 宇宙最強攻略:30 天帶你從入門到入坑系列文
請注意,透過 Flipper Zero 所學到的技術與知識,主要目的是提升個人技術能力與資訊安全意識。我們強烈呼籲各位,不要將這些知識應用於任何違法活動。您有責任確保所學知識的合法用途。針對今天的主題,大家務必要注意以下幾點:
絕對不要測試不屬於自己的設備,或是未經授權的設備。
切勿測試您自己日常使用的或生活必需的裝置。
重放攻擊(Replay Attack)或是訊號模糊測試(Fuzzing Signals)有可能導致接收器與發射設備不同步,並可能造成損壞,後果須自行承擔。
昨天有說到碼(code)實際上是一串位元序列(bit pattern),以固定碼(static code)來說,這個位元序列通常包含:
前導碼(preamble):前幾個固定長度的高低脈衝,用來讓呼叫接收端並對其時脈。
同步碼(sync / header):讓接收端知道「從哪裡開始計算資料」。
資料區(payload):實際傳送的資料,其中又包含:
可能的補強位(例如反相位、簡單 checksum),用以提升接收正確率。
結尾碼(stop / trailer):表示這串資料的結束。
[Preamble] [Sync] [Address=10101011] [Command=01] [Parity=1] [Stop]
通常所使用的晶片,會定義了 bit 長度、編碼方式、傳輸順序等,也就是說格式主要會由 IC 設計公司(協定)或是遙控器製造商所決定,沒有必然一定多長。
滾動碼(rolling code)既然也是碼,當然也遵守著跟固定碼(static code)類似的規則,那既然要好好說明 rolling code,當然也要好好說明它的資料結構是什麼樣子的。
參考 Kazma 的文章與 Derek Jamison的影片內容,下圖首先要介紹的是 Security+ 1.0 這個協定的滾動碼,這個舊一代的協定通常用在 LiftMaster 車庫門系統,在這個協議中,所有資料只有進行 encoded(編碼),卻沒有進行 encrypted(加密)。
這兩個詞彙乍看好像意思差不多,但實際上卻有很大的差異,encoded 是把資料按照某個格式進行編碼,透過轉換資料格式,讓不同系統都能夠互相溝通(讀取、傳輸、存儲),像是人類語言一樣,不同國家的人說不同的語言,但只要按照某個格式進行翻譯,就能夠互相溝通。
而 encrypted 則是為了保護資料隱私或安全,所以會把資料使用某種演算法進行加密,使得資料在傳輸過程中無法被解讀,即便截這到資料並知道演算法,如果沒有正確的金鑰,也無法解密資料,可以想像成把中文寫成只有你和朋友才看得懂的暗號,還需要有能夠解讀這個特殊暗號的筆記本(金鑰),才能真的看得懂。
回到 Security+ 1.0 這個協定,因為資料只進行了編碼,卻沒有進行加密,所以只要知道資料的格式,就可以輕鬆地解讀資料,現在我們就來看看 Security+ 1.0 的資料結構是什麼樣子的。
第一行:
Security+ 1.0 42b 433.92 AM
這邊 Kazma 有提到這邊其實是用三進位(trit),所以 42b 的 b 並不是代表 bits,而是 bit length,對應到的傳輸的內容,會有 42 個符號。
第二行:
Key: 0x63A5EB6D E6000044
Flipper Zero 把一個按鍵的有效內容分成兩段顯示:
0x63A5EB6D
:每次按同一顆按鍵都不變的那部分(含裝置序號與少量標誌位)。0xE6000044
:每按一次就變的計數器/滾動碼。而「Key」就是把 Fixed + Rolling 這兩段拼在一起,方便辨識同一支遙控/同一顆按鍵。
第三行:
id:1 id:0 Btn:right
1 = left、0 = middle、2 = right → 這例子是 2,所以顯示 right。
id0: 2、id1: 1:這兩個值來自 Fixed 段倒數第 2、倒數第 3 個 trit
第四行:
Sn: 0x03B0CFD4
Sn 是「序號(Serial number)」,做法是把 Fixed 段十六進位用三進位寫出來後,去掉末端三個 trit(Btn / id0 / id1),剩下前面的那串三進位數字就是序號的本體:
0x63A5EB6D = 11022111211011011021122
去掉末端三個 trit 後,再轉換為十六進位:
11022111211011011021 = 03B0CFD4
第五行:
Cnt: 0xE6000044
Cnt 是滾動計數器(rolling counter),每按一次就遞增(或依協定規則前進),是滾動碼的關鍵。接收端只接受「落在可接受視窗內」的較新值。
當使用者每按一次新的按鍵時,就會把計數器往前推進,變成新的值,例如:
0xE6000044 -> 0xE6000045 -> 0xE6000046 -> ...
第六行:
Sw_id: 0x2
即是「按鍵代號(switch id)」,其實和上面的 Btn:right 是同一件事,只不是另一種表達方式——「0x2 代表右鍵」。
這邊需要補充一下所謂的 Packet 1 與 Packet 2,實際上就是將本來的 Key: 0x63A5EB6D E6000044
從十六進位轉換成三進位,會分別得到:
Packet 1: *01101111002001211102
Packet 2: *01122211122012110021
*
是起始符號(sync,用來讓接收端對齊),後面接著一串 trits。
而 Packet 1 與 Packet 2 的長度為 42 trits,這就是爲什麼 Flipper 螢幕顯示 42b。
最後使用者按下遙控器後,接收端會拿到「序號」「按鍵」「滾動值」,用內部的密鑰與視窗機制驗證是否為「這支遙控器」且「未用過的有效下一碼」,如果通過驗證,就會執行相對應的功能。
認識了 Security+ 1.0 在 Flipper Zero 上的呈現,我們明天再接續認識 KeeLog 吧!